package com.yao;

import static java.util.Comparator.*;
import static java.util.stream.Collectors.*;

import java.util.ArrayList;
import java.util.Currency;
import java.util.DoubleSummaryStatistics;
import java.util.HashMap;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.LongSummaryStatistics;
import java.util.Map;
import java.util.stream.Collectors;

import com.yao.common.Startup;
import com.yao.entity.Dish;
import com.yao.entity.Transaction;

/**
 * 第六章 - 用流收集数据
 * 
 * 用Collectors类创建和使用收集器
 * 将数据流归约为一个值
 * 汇总：归约的特殊情况
 * 数据分组和分区
 * 开发自己的自定义收集器
 * 
 * @author yaoym
 * @date 2018年1月30日 下午3:18:08
 * @version V1.0
 */
public class SessionSixth {

	static List<Transaction> transactions;
	
	static List<Dish> menu;
	
	/**
	 * 数据初始化
	 */
	static {
		transactions = Startup.getTransactions();
		menu = Startup.getMenu();
	}
	
	/*把列表中的交易按货币分组。*/
	static void traningOne(){
		//以前的做法
		//1.创建一个累计交易分组的map
		Map<Currency, List<Transaction>> transactionsByCurrencies = new HashMap<>();
		//2.迭代transactions的List
		for (Transaction transaction : transactions) {
			//3.按货币提取Transaction
			Currency currency = transaction.getCurrency();
			List<Transaction> transactionsForCurrency = transactionsByCurrencies.get(currency);
			
			if (transactionsForCurrency == null) {
				transactionsForCurrency = new ArrayList<>();
				transactionsByCurrencies.put(currency, transactionsForCurrency);
			}
			//将当前遍历的Transaction加入同一货币的Transaction的List
			transactionsForCurrency.add(transaction);
		}
		//////////////////////////////////////////////////////////////////////////////////////////////
		//新的做法
		//用collect
		transactionsByCurrencies = transactions.stream().collect(groupingBy(Transaction::getCurrency));
	}
	
	
	/*6.2 归约和汇总*/
	static void traningTwo(){
		//查询菜单有多少个菜
		long howManyDishes = menu.stream().collect(Collectors.counting());
		howManyDishes = menu.stream().count();
		
		//查询热量最高和最低
		menu.stream().collect(maxBy(comparing(Dish::getCalories))).ifPresent(System.out::println);
		menu.stream().collect(minBy(comparing(Dish::getCalories))).ifPresent(System.out::println);
		
		//求菜单总热量\
		int totalCalories = menu.stream().mapToInt(Dish::getCalories).sum();
		totalCalories = menu.stream().collect(summingInt(Dish::getCalories)).intValue();
		
		double averagingCarlories = menu.stream().collect(averagingDouble(Dish::getCalories)).longValue();

		System.out.println("菜单总热量："+totalCalories+" ,平均热量："+averagingCarlories);
		
		//通过summarizingInt一次获取所需数值
		IntSummaryStatistics menuStatistics = menu.stream().collect(summarizingInt(Dish::getCalories));
		System.out.println("所有数据在此：："+menuStatistics);
		
		LongSummaryStatistics menuStatisticsLong = menu.stream().collect(summarizingLong(Dish::getCalories));
		System.out.println("所有数据在此(Long)：："+menuStatisticsLong);
		
		DoubleSummaryStatistics menuStatisticsDouble = menu.stream().collect(summarizingDouble(Dish::getCalories));
		System.out.println("所有数据在此(Double)：："+menuStatisticsDouble);
		
		//拼接字符串
		String shortMenu = menu.stream().map(Dish::getName).collect(joining(", ")); 
		
		System.out.println(shortMenu);
	}
	

	public static void main(String[] args) {
		traningTwo();
	}

}
